package com.xiaoyu.lanling.feature.videocall.util

import android.annotation.TargetApi
import android.app.Notification
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.os.Build
import androidx.core.app.NotificationCompat
import com.xiaoyu.base.app.AppContext
import com.xiaoyu.base.data.UserData
import com.xiaoyu.base.data.UserInfoDataProvider
import com.xiaoyu.base.model.User
import com.xiaoyu.base.utils.RxUtils
import com.xiaoyu.lanling.R
import com.xiaoyu.lanling.common.Constant
import com.xiaoyu.lanling.data.NotificationData
import com.xiaoyu.lanling.feature.videocall.activity.VideoCallActivity
import com.xiaoyu.lanling.feature.videocall.service.VideoCallService
import com.xiaoyu.lib_av.datamodel.CallParams
import io.reactivex.Observable
import io.reactivex.disposables.Disposable
import java.util.concurrent.TimeUnit

class VideoCallNotificationUtils private constructor() {

    var dismissable = false
    private var delay: Disposable? = null
    private var mCallServiceIntent: Intent? = null

    fun clearAllNotification() {
        try {
            val manager = AppContext.getContext().getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
            manager.cancelAll()
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    fun showNotification(callParams: CallParams, isCaller: Boolean, isReceive: Boolean) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            dismissable = false
            startCallingService(callParams, isCaller, isReceive)
            RxUtils.disposable(delay)
            delay = Observable.timer(6, TimeUnit.SECONDS)
                    .subscribe { dismissable = true }
        } else {
            showNotificationBelowApi26(callParams, isCaller, isReceive)
        }
    }

    fun dismissNotification() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            if (dismissable) {
                stopCallingService()
            }
        } else {
            dismissCallNotificationBelowApi26()
        }
    }

    fun createVideoCallIntent(callParams: CallParams, isCaller: Boolean): Intent? {
        val intent = Intent(AppContext.getContext(), VideoCallActivity::class.java)
        intent.putExtra(Constant.IntentKey.KEY_CHAT_CALL_CALL_PARAM, callParams)
        intent.putExtra(Constant.PARAM_FROM, "")
        intent.putExtra(Constant.IntentKey.KEY_CHAT_CALL_IS_CALLER, isCaller)
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP)
        return intent
    }

    fun buildNotification(title: CharSequence?, text: CharSequence?, pendingIntent: PendingIntent?): Notification {
        return NotificationCompat.Builder(AppContext.getContext(), NotificationData.ChannelId.CALL_VIDEO_CALL)
                .setContentTitle(title)
                .setContentText(text)
                .setContentIntent(pendingIntent)
                .setVibrate(NotificationData.VIBRATE_PATTERN)
                .setTicker(text)
                .setWhen(System.currentTimeMillis())
                .setDefaults(Notification.DEFAULT_ALL)
                .setSmallIcon(R.drawable.mipush_small_notification)
                .setPriority(Notification.PRIORITY_HIGH)
                .setAutoCancel(true)
                .build()
    }

    private fun showNotificationBelowApi26(callParams: CallParams, isCaller: Boolean, isReceive: Boolean) {
        val intent = createVideoCallIntent(callParams, isCaller)
        val text = getNotificationText(isReceive)
        val isSelf = UserData.getInstance().isSelf(callParams.fromUser.uid)
        val user: User = UserInfoDataProvider.getInstance().fetchFromMemory(callParams.getFuid(isSelf))
        val pendingIntent = PendingIntent.getActivity(AppContext.getContext(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
        showChatCallNotificationBase(user.name, text, pendingIntent)
    }

    private fun createCallServiceIntent(callParams: CallParams, isCaller: Boolean, isReceive: Boolean): Intent? {
        val intent = Intent(AppContext.getContext(), VideoCallService::class.java)
        intent.putExtra(Constant.IntentKey.KEY_CHAT_CALL_CALL_PARAM, callParams)
        intent.putExtra(Constant.IntentKey.KEY_CHAT_CALL_IS_CALLER, isCaller)
        intent.putExtra(Constant.IntentKey.KEY_CHAT_CALL_IS_RECEIVE, isReceive)
        return intent
    }

    private fun showChatCallNotificationBase(title: String, text: CharSequence, pendingIntent: PendingIntent) {
        dismissCallNotificationBelowApi26()
        val notification = buildNotification(title, text, pendingIntent)
        notification.flags = Notification.FLAG_ONGOING_EVENT or Notification.FLAG_NO_CLEAR
        val manager = AppContext.getContext().getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
        manager.notify(NotificationData.ChannelTag.CALL_VIDEO_CALL, NotificationData.NotificationId.CALL_VIDEO_CALL, notification)
    }

    private fun dismissCallNotificationBelowApi26() {
        try {
            val manager = AppContext.getContext().getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
            manager.cancel(NotificationData.ChannelTag.CALL_VIDEO_CALL, NotificationData.NotificationId.CALL_VIDEO_CALL)
        } catch (e: java.lang.Exception) {
            e.printStackTrace()
        }
    }

    @TargetApi(Build.VERSION_CODES.O)
    private fun startCallingService(callParams: CallParams, isCaller: Boolean, isReceive: Boolean) {
        mCallServiceIntent = createCallServiceIntent(callParams, isCaller, isReceive)
        AppContext.getContext().startForegroundService(mCallServiceIntent)
    }

    @TargetApi(Build.VERSION_CODES.O)
    private fun stopCallingService() {
        if (mCallServiceIntent == null) {
            return
        }
        AppContext.getContext().stopService(mCallServiceIntent)
    }

    companion object {
        val instance by lazy { VideoCallNotificationUtils() }

        fun getNotificationText(isReceive: Boolean): CharSequence {
            return AppContext.getString(if (isReceive) R.string.video_call_notification_receive_text else R.string.video_call_notification_calling_text)
        }
    }
}